package es.manuel.maa.service.impl;

import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;
import javax.persistence.NoResultException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import es.manuel.maa.dao.UserDao;
import es.manuel.maa.dao.impl.UserJpaDaoImpl;
import es.manuel.maa.dto.UserDetailsImpl;
import es.manuel.maa.model.User;
import es.manuel.maa.service.UserService;
import es.manuel.maa.util.PasswordUtil;

@Service(value = UserServiceImpl.ID)
public class UserServiceImpl implements UserService {

	/**
	 * ID
	 */
	public static final String ID = "userServiceImpl";

	@Autowired
	@Qualifier(value = "passwordLength")
	private Integer passwordLength;

	@Autowired
	@Qualifier(value = "mailFrom")
	private String mailFrom;

	@Autowired
	@Qualifier(value = UserJpaDaoImpl.ID)
	private UserDao userDao;

	@Autowired
	@Qualifier(value = "passwordEncoder")
	private PasswordEncoder passwordEncoder;

	@Transactional(readOnly = true)
	@Override
	public boolean isUsernameAvailable(String username) {
		try {
			User user = userDao.getByUsername(username);
			return user == null;
		} catch (NoResultException e) {
			return true;
		}
	}

	@Transactional(rollbackFor = { MessagingException.class })
	@Override
	public void register(User user, String mailSubject, String mailBody)
			throws MessagingException {

		String password = PasswordUtil.getPassword(passwordLength);
		user.setPassword(passwordEncoder.encodePassword(password,
				user.getUsername()));
		userDao.insert(user);

		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);
		JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
		mailSender.setSession(session);
		MimeMessage message = new MimeMessage(session);
		MimeMessageHelper helper = new MimeMessageHelper(message);
		helper.setTo(user.getEmail());
		helper.setFrom(mailFrom);
		helper.setSubject(mailSubject);
		helper.setText(mailBody.replace("<username />", user.getUsername())
				.replace("<password />", password), true);
		helper.getMimeMessage();
		Transport.send(message);
	}

	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		try {
			User user = userDao.getByUsername(username);
			if (user == null) {
				throw new UsernameNotFoundException(String.format(
						"No se ha encontrado el usuario : [%s]", username));
			}
			return new UserDetailsImpl(user);
		} catch (UsernameNotFoundException e) {
			throw e;
		} catch (NoResultException e) {
			throw new UsernameNotFoundException(String.format(
					"No se ha encontrado el usuario : [%s]", username), e);
		} catch (Throwable e) {
			throw new UsernameNotFoundException(
					String.format(
							"Ha ocurrido un error buscando el usuario : [%s]",
							username), e);
		}
	}
}
